#pragma once

#include <iostream>
#include <string>
#include <memory>
#include <functional>
#include <thread>
#include <cstdlib>
#include <cstring>
#include <cerrno>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include "err.hpp"
#include "easylog.hpp"
#include "../easysock.hpp"

namespace tcp
{

const int backlog = 16;

class tcp_server;

struct thread_args
{
public:

    thread_args(tcp_server* tp, int fd, const std::string& who)
        : ts(tp), sock(fd), cli(who)
    {}

public:
    tcp_server* ts;
    int sock;
    std::string cli;
};

class tcp_server : public inet::tcp::server
{
public:
    using func_t = std::function<std::string(const std::string&)>;

public:
    tcp_server(func_t func, uint16_t port) 
        : server(port)
        , _quit(false)
        , _func(func)
    {}

    ~tcp_server()
    {
    }

    void init_server()
    {
    }

    void start()
    {
        while (!_quit)
        {
            std::string cip;
            uint16_t cport;
            int sock = accept(&cip, &cport);
            if (sock < 0)
            {
                ERROR("accept error");
                continue;
            }

            std::string cli = '[' + cip + ':' + std::to_string(cport) + ']';

            INFO("accept success sock %d form %d, %s", sock, _sock, cli.c_str());

            //v1
            service(sock, cli);
        }
    }

    void service(int sock, const std::string& cli)
    {
        std::string msg;
        ssize_t s = recv(sock, &msg, 1024);
        if (s > 0)
        {
            std::string res = _func(msg);
            std::cout << cli << "# " << res << std::endl;
            send(sock, res);
        }

        close(sock);
    }

private:
    bool _quit;
    func_t _func;
};

}
